Skip to content

Align manifest assembly MVID table to 4 bytes in composite R2R images#129017

Open
jtschuster wants to merge 7 commits into
dotnet:mainfrom
jtschuster:jtschuster/ideal-funicular
Open

Align manifest assembly MVID table to 4 bytes in composite R2R images#129017
jtschuster wants to merge 7 commits into
dotnet:mainfrom
jtschuster:jtschuster/ideal-funicular

Conversation

@jtschuster
Copy link
Copy Markdown
Member

@jtschuster jtschuster commented Jun 4, 2026

Summary

Fixes a 32-bit ARM SIGBUS (alignment fault) when running composite Ready-to-Run images.

ManifestAssemblyMvidHeaderNode emits the assembly MVID table — a packed array of 16-byte GUIDs — with alignment: 1. The CoreCLR runtime reads each entry as a GUID by value (ReadyToRunInfo in readytoruninfo.cpp), and GUID has a natural alignment of 4. When the table landed on a non-4-aligned RVA, ARM32 faulted with BUS_ADRALN because it does not permit unaligned multi-word loads. x64/arm64 tolerate the unaligned access, so the crash only manifested on ARM32.

Why the table could land unaligned

The table's RVA depends on the size of the preceding Ordered ReadOnlyData node. In composites built with debug directory entries (e.g. --pdb), an odd-sized NativeDebugDirectoryEntryNode (RSDS record) sorts between RuntimeFunctionsTableNode and the MVID table and can push it off a 4-byte boundary.

The fix

Set the node alignment to 4 so the table is padded to a valid boundary regardless of predecessor size.

Validation

Reproduced on current main with a controlled experiment (identical inputs and output name, so the predecessor node is byte-for-byte identical; the only variable is the alignment value):

NativeDebugDirectoryEntryNode @ 0x6D440, size 0x22 (34 ≡ 2 mod 4) -> ends 0x6D462
  alignment:1 (before):  MVID @ 0x6D462   &3 = 2  -> UNALIGNED -> SIGBUS
  alignment:4 (after):   MVID @ 0x6D464   &3 = 0  -> ALIGNED (2 bytes padding)

This matches the structure of a real failing ARM32 image, whose MVID table sat at RVA 0x28f49 (&3 = 1), consistent with the fault's si_addr in the kernel core.

Note

This pull request was authored with assistance from GitHub Copilot.

ManifestAssemblyMvidHeaderNode emitted the assembly MVID table (a packed
array of 16-byte GUIDs) with alignment 1. The CoreCLR runtime reads each
entry as a GUID by value, and GUID has a natural alignment of 4. When the
table landed on a non-4-aligned RVA, 32-bit ARM faulted with BUS_ADRALN
(SIGBUS) because it does not permit unaligned multi-word loads. Other
architectures tolerated the unaligned access, so the crash only manifested
on ARM32.

The table's RVA depends on the size of the preceding Ordered ReadOnlyData
node. In composites built with debug directory entries (e.g. --pdb), an
odd-sized NativeDebugDirectoryEntryNode can precede the MVID table and push
it off a 4-byte boundary. Setting the alignment to 4 pads the table to a
valid boundary regardless of predecessor size.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 4, 2026 22:10
@github-actions github-actions Bot added the area-crossgen2-coreclr only use for closed issues label Jun 4, 2026
@jtschuster
Copy link
Copy Markdown
Member Author

/azp run runtime-coreclr crossgen2-composite

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the ReadyToRun (crossgen2) emitter for composite images so the manifest assembly MVID table is emitted with 4-byte alignment, preventing potential unaligned GUID loads by the CoreCLR runtime on alignment-sensitive architectures (notably 32-bit ARM).

Changes:

  • Change ManifestAssemblyMvidHeaderNode output alignment from 1 to 4 bytes.
  • Add an explanatory comment documenting the runtime read pattern and the alignment requirement.

…yAnalysis/ReadyToRun/ManifestAssemblyMvidHeaderNode.cs

Co-authored-by: Jan Kotas <jkotas@microsoft.com>
Copilot AI review requested due to automatic review settings June 5, 2026 16:28
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 1 comment.

jtschuster and others added 5 commits June 5, 2026 09:48
Locks the 4-byte alignment contract of the manifest assembly MVID table in
composite R2R images. The runtime reads each entry as a GUID by value, so a
misaligned table causes alignment faults (SIGBUS) on 32-bit ARM. Adds the
R2RAssert.ManifestAssemblyMvidsTableIsAligned helper and a composite test.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The cross-platform invariant test cannot reproduce the original misalignment
because a plain composite always lays the MVID table 4-byte aligned. Passing
--pdb injects an odd-sized NativeDebugDirectoryEntryNode immediately before the
table, which is the exact layout that exposed the bug: without the fix the MVID
table lands on a non-4-aligned RVA (verified: RVA 0x107AF unfixed vs 0x107B0
fixed for these inputs).

--pdb writes the NI PDB through Microsoft.DiaSymReader.Native, which only exists
on Windows, so the test is gated with [ConditionalFact(nameof(IsWindows))] and
skips elsewhere.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove redundant comments where the assertion is self-describing, condense the
--pdb rationale, and replace the always-4 alignment parameter with a
RequiredAlignment constant so the helper's contract matches its documentation.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…re-green

The odd-sized native debug directory entry that exposes the misalignment derives
from the composite output name length, so a rename can silently move the MVID
table back onto a 4-byte boundary. Warn future maintainers to re-verify.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 5, 2026 20:53
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

@jtschuster jtschuster requested a review from davidwrighton June 5, 2026 22:08
@jtschuster jtschuster added area-ReadyToRun and removed area-crossgen2-coreclr only use for closed issues labels Jun 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

4 participants